package com.zxf.appliction.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zxf.appliction.util.PropertiesFileUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;

import java.lang.reflect.Method;

/**
 * 查询缓存
 *
 * Created by ouba on 2017/4/13.
 */

@Configuration
@EnableCaching
public class RedisConfiguration extends CachingConfigurerSupport {

    private final Logger logger = LoggerFactory.getLogger(RedisConfiguration.class);
    private static String host;
    private static int port;
    private static int timeout;
    private static int maxActive;
    private static int maxIdle;
    private static int maxWaitMills;
    private static boolean testOnBorrow;
    private static String password;

    static {
        host = PropertiesFileUtils.getInstance("redis").get("spring.redis.host");
    port = PropertiesFileUtils.getInstance("redis").getInt("spring.redis.port");
    timeout = PropertiesFileUtils.getInstance("redis").getInt("spring.redis.timeout");
    maxActive = PropertiesFileUtils.getInstance("redis").getInt("spring.redis.pool.max-active");
    maxIdle = PropertiesFileUtils.getInstance("redis").getInt("spring.redis.pool.max-idle");
    maxWaitMills = PropertiesFileUtils.getInstance("redis").getInt("spring.redis.pool.max-wait");
    testOnBorrow = PropertiesFileUtils.getInstance("redis").getBoolean("spring.redis.test-on-borrow");
    password = PropertiesFileUtils.getInstance("redis").get("spring.redis.password");
}


    /**
     * 缓存key策略
     *
     * @return
     */
    @Bean
    public KeyGenerator redisKeyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

    @Bean
    public CacheManager cacheManager(RedisTemplate<?, ?> redisTemplate) {
        return new RedisCacheManager(redisTemplate);
    }

    @Bean(name = "jedisConnectionFactory")
    public JedisConnectionFactory JedisConnectionFactory() {
       JedisConnectionFactory factory = new JedisConnectionFactory();
       factory.setHostName(host);
       factory.setPort(port);
       factory.setTimeout(timeout);
       factory.setPassword(password);

       JedisPoolConfig config = new JedisPoolConfig();
       config.setMaxTotal(maxActive);
       config.setMaxIdle(maxIdle);
       config.setTestOnBorrow(testOnBorrow);
       config.setMaxWaitMillis(maxWaitMills);
       factory.setPoolConfig(config);
       return factory;

    }

    /**
     * 缓存序列化
     *
     * @param factory
     * @return
     */
    @Bean
    public RedisTemplate<?, ?> redisTemplate(@Qualifier("jedisConnectionFactory") RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);
        Jackson2JsonRedisSerializer redisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        redisSerializer.setObjectMapper(objectMapper);
        template.setValueSerializer(redisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}
